<!DOCTYPE html>
<html lang="en">

<head>
    <title>three.js webgl - camera cinematic</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link type="text/css" rel="stylesheet" href="../css/style.css">
    <style>
        body {
            background-color: #000;;
            color: #000;
        }

        a {
            color: #08f;
        }

        .toast {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            padding: 20px 50px;
            border-radius: 10px;
            background-color: rgba(0, 0, 0, 0.8);
            color: #fff;
        }
    </style>
</head>

<body>

    <button id="copy" data-clipboard-text="Just because you can doesn't mean you should — clipboard.js"></button>


    <script id="vertexShader" type="x-shader/x-fragment">
        varying vec4 vModelPosition;
        varying vec4 vViewPosition;
        varying vec3 vPosition;
        varying vec2 vUv;
        void main(){
            vec4 modelPosition = modelMatrix * vec4( position, 1.0 ); 
            vec4 viewPosition = viewMatrix * vec4( position, 1.0 ); 

            gl_Position = projectionMatrix * viewMatrix * modelPosition;
            vUv = uv;
            vViewPosition = viewPosition;
            vModelPosition = modelPosition;
            vPosition = position;
        }
    </script>

    <script id="fragmentShader" type="x-shader/x-fragment">
        // 旋转函数
        varying vec4 vViewPosition;
        varying vec4 vModelPosition;
        varying vec3 vPosition;
        varying vec2 vUv;
        uniform float uTime;

        void main(){
            float color =1.0-step(0.2,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)));
            gl_FragColor =vec4(color,color,color,1);
        }
    </script>

    <script src="../build/three.min.js"></script>
    <script src="../js/controls/OrbitControls.js"></script>

    <script src="../../js/gsap/gsap.min.js"></script>
    <script src="../../js/clipboard/clipboard.min.js"></script>

    <script src="./init.js?v=20220101"></script>
    <script>
        const meshs = []
        create1();
        function create1() {
            for (var i = 3; i >= -2; i--) {
                for (var j = -4; j <= 4; j++) {
                    const material = new THREE.ShaderMaterial({
                        transparent: true,
                        side: THREE.DoubleSide,
                        vertexShader: ` 
                        varying vec2 vUv;
                        void main(){ 
                            gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ); 
                            vUv=uv;
                        } `,
                        fragmentShader: ` 
                        // fragmentFn;
                        varying vec2 vUv;
                        
                        void main(){ 
                            float color = 1.0;
                            // replaceFragmentShader;
                            gl_FragColor =vec4(color,color,color,1.0);
                        } 
                        
                        `,
                    });
                    const m = new THREE.Mesh(new THREE.PlaneBufferGeometry(1, 1), material);
                    m.scale.set(0.8, 0.8, 1)
                    m.position.set(j, i, 0)
                    scene.add(m);
                    meshs.push(m)
                }
            }


            setFrag(meshs[1], 'uv渐变,从左到右', ` float color = vUv.x; `)

            setFrag(meshs[2], 'uv渐变,从右到左', ` float color = 1.0-vUv.x; `)

            setFrag(meshs[3], 'uv渐变,从上到下', ` float color = vUv.y; `)

            setFrag(meshs[4], 'uv渐变,从下到上', `float color = 1.0-vUv.y;`)

            setFrag(meshs[5], 'uv短范围内渐变', `float color = (1.0-vUv.y) * 2.0;`)

            setFrag(meshs[6], '取模达到反复效果', `float color = mod(vUv.y * 4.0 , 1.0);`)

            setFrag(meshs[7], 'step(edge, x) 如果x < edge，返回0.0，否则返回1.0', `float color =  mod(vUv.y * 4.0 , 1.0);color = step(0.5,color);`)

            setFrag(meshs[8], 'step(edge, x) 如果x < edge，返回0.0，否则返回1.0', `
                float color =  mod(vUv.y * 4.0 , 1.0) ;
                color = step(0.8,color);
            `)

            setFrag(meshs[9], 'step(edge, x) 如果x < edge，返回0.0，否则返回1.0', `
                float color =  mod(vUv.x * 4.0 , 1.0) ;
                color = step(0.8,color);
            `)

            setFrag(meshs[10], '条纹相加', `
                float color = step(0.8, mod(vUv.x * 4.0 , 1.0)) ;
                color += step(0.8, mod(vUv.y * 4.0 , 1.0)) ;
            `)

            setFrag(meshs[11], '条纹相乘', `
                float color = step(0.8, mod(vUv.x * 4.0 , 1.0)) ;
                color *= step(0.8, mod(vUv.y * 4.0 , 1.0)) ;
            `)

            setFrag(meshs[12], '条纹相减', `
                float color = step(0.8, mod(vUv.x * 4.0 , 1.0)) ;
                color -= step(0.8, mod(vUv.y * 4.0 , 1.0)) ;
            `)

            setFrag(meshs[13], '方块图形', `
                float color = step(0.2, mod(vUv.x * 4.0 , 1.0)) ;
                color *= step(0.2, mod(vUv.y * 4.0 , 1.0)) ;
            `)

            setFrag(meshs[14], 'T型图', `
                float barX = step(0.4, mod(vUv.x * 4.0 - 0.2 , 1.0))*step(0.8, mod(vUv.y * 4.0 , 1.0)) ;
                float barY = step(0.4, mod(vUv.y * 4.0 , 1.0))*step(0.8, mod(vUv.x * 4.0 , 1.0))  ;
                float color = barX+barY;
            `)

            setFrag(meshs[15], 'abs绝对值', `
                float color = abs(vUv.x - 0.5);
            `)

            setFrag(meshs[16], 'min(x,y)取2个值的最小值', `
                float color =min(abs(vUv.x - 0.5), abs(vUv.y - 0.5))  ;
            `)

            setFrag(meshs[17], 'min(x,y)取2个值的最大值', `
                float color =max(abs(vUv.x - 0.5), abs(vUv.y - 0.5))  ;
            `)

            setFrag(meshs[18], 'TODO', `
                float color =step(0.2,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)))   ;
            `)

            setFrag(meshs[19], '小正方形', `
                float color =1.0-step(0.2,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)))   ;
            `)

            setFrag(meshs[20], '利用取整，实现条纹渐变', `
                float color = floor(vUv.x*4.0)/4.0;
            `)

            // setFrag(meshs[21],'TODO', `
            //     float color =min(abs(vUv.x - 0.5), abs(vUv.y - 0.5))  ;
            // `)

            setFrag(meshs[22], '条纹相乘，实现渐变格子', `
                float color = floor(vUv.x*4.0)/4.0*floor(vUv.y*4.0)/4.0;
            `)

            setFrag(meshs[23], '向上取整', `
                float color = ceil(vUv.x*4.0)/4.0*ceil(vUv.y*4.0)/4.0;
            `)


            setFrag(meshs[24], '随机效果', `
                // 随机函数
                float random (vec2 st) {
                    return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
                }
            `, '// fragmentFn;')
            setFrag(meshs[24], '', ` float color = random(vUv); `)

            setFrag(meshs[25], '随机,格子效果', `
                // 随机函数
                float random (vec2 st) {
                    return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
                }
            `, '// fragmentFn;')
            setFrag(meshs[25], `
                float color = ceil(vUv.x*4.0)/4.0*ceil(vUv.y*4.0)/4.0;
                color = random(vec2(color,color));
            `)


            setFrag(meshs[26], '依据length返回向量长度', ` float color = length(vUv); `)

            setFrag(meshs[27], '根据distance技术2个向量的距离', `float color =1.0 - distance(vUv,vec2(0.5,0.5));`)

            setFrag(meshs[28], '相除，实现星星', `float color =0.5 / distance(vUv,vec2(0.5,0.5)) - 1.0;`)
            setFrag(meshs[28], '', `gl_FragColor =vec4(color,color,color,color);`, "gl_FragColor =vec4(color,color,color,1.0);")

            setFrag(meshs[29], '设置vUv水平或者竖直变量', `float color =0.5 / distance(vec2(vUv.x,(vUv.y-0.5)*5.0),vec2(0.5,0.5)) - 1.0;`)
            setFrag(meshs[29], '', `gl_FragColor =vec4(color,color,color,color);`, "gl_FragColor =vec4(color,color,color,1.0);")

            setFrag(meshs[30], '十字交叉的星星', `
                float  color = 0.5 / distance(vec2(vUv.x,(vUv.y-0.5)*5.0+0.5),vec2(0.5,0.5)) - 1.0;
                color += 0.5 / distance(vec2(vUv.y,(vUv.x-0.5)*5.0+0.5),vec2(0.5,0.5)) - 1.0;
            `)
            setFrag(meshs[30], '', `gl_FragColor =vec4(color,color,color,color);`, "gl_FragColor =vec4(color,color,color,1.0);")

            // 旋转的飞镖   
            rotateDarts();

            setFrag(meshs[31], '日本国旗', ` float color = step(0.5,distance(vUv,vec2(0.5))+0.25) ;`)

            setFrag(meshs[32], '绘制圆', ` float color = 1.0 - step(0.5,distance(vUv,vec2(0.5))+0.25) ;`)

            setFrag(meshs[33], '圆环', `
                float color = step(0.5,distance(vUv,vec2(0.5))+0.35) ;
                color *= (1.0 - step(0.5,distance(vUv,vec2(0.5))+0.25)) ;
            `)

            setFrag(meshs[34], '渐变环', `float color =  abs(distance(vUv,vec2(0.5))-0.25) ;`)

            setFrag(meshs[35], '打靶', `float color = step(0.1,abs(distance(vUv,vec2(0.5))-0.25)); `)

            setFrag(meshs[36], '圆环', `float color = 1.0 - step(0.1,abs(distance(vUv,vec2(0.5))-0.25));`)

            setFrag(meshs[37], '波浪环', `
                vec2 waveUv = vec2(
                    vUv.x,
                    vUv.y+sin(vUv.x*30.0)*0.1
                );
                float color = 1.0 - step(0.01,abs(distance(waveUv,vec2(0.5))-0.25))   ;
            `);

            setFrag(meshs[38], 'sin三角函数绘制随机图形', `
                vec2 waveUv = vec2(
                    vUv.x+sin(vUv.y*30.0)*0.1,
                    vUv.y+sin(vUv.x*30.0)*0.1
                );
                float color = 1.0 - step(0.01,abs(distance(waveUv,vec2(0.5))-0.25))   ;
            `);

            setFrag(meshs[39], 'sin三角函数绘制随机图形,增大sin里面的值', `
                vec2 waveUv = vec2(
                    vUv.x+sin(vUv.y*100.0)*0.1,
                    vUv.y+sin(vUv.x*100.0)*0.1
                );
                float color = 1.0 - step(0.01,abs(distance(waveUv,vec2(0.5))-0.25))   ;
            `);

            setFrag(meshs[40], 'atan根据角度显示视图', `
                float angle = atan(vUv.x,vUv.y);
                float color = angle;
            `);

            setFrag(meshs[41], 'atan根据角度实现螺旋渐变', `
                // 方式1
                // float alpha =  1.0 - step(0.5,distance(vUv,vec2(0.5)));
                // float angle = atan(vUv.x-0.5,vUv.y-0.5);
                // float color = (angle+3.14)/6.28;
                // gl_FragColor =vec4(color,color,color,alpha);

                // 方式2
                float angle = atan(vUv.x-0.5,vUv.y-0.5);
                float color = (angle+3.14)/6.28;
            `);

            // 旋转(类似雷达)
            rotateLD();

            setFrag(meshs[43], '万花筒', `
                float angle = atan(vUv.x-0.5,vUv.y-0.5)/3.14;
                float color = mod(angle*5.0,1.0);
            `);

            setFrag(meshs[44], '光芒四射', `
                float angle = atan(vUv.x-0.5,vUv.y-0.5)/(2.0*3.14);
                float color = sin(angle*100.0);
            `);


            addNoise(meshs[45])
            setFrag(meshs[45], '使用噪声实现烟雾、波纹效果', `
                float color = noise(vUv);
                
            `);

            addNoise(meshs[46])
            setFrag(meshs[46], '使noise加大', `
                float color = noise(vUv * 10.0);
                // float color = noise(vUv * 100.0);
            `);


            // 通过时间设置波形
            ripple()

            addCNoise(meshs[48])
            setFrag(meshs[48], '路径', `float color = abs(cnoise(vUv * 10.0)) ;`);

            addCNoise(meshs[49])
            setFrag(meshs[49], '发光路径', `float color =1.0 - abs(cnoise(vUv * 10.0)) ;`);

            //波纹效果
            ripple1()

            addCNoise(meshs[51])
            setFrag(meshs[51], '', `float color = step(0.9,sin(cnoise(vUv * 10.0)*20.0)) ;`);



            addCNoise(meshs[52])
            setFrag(meshs[52], '混合函数混颜色', `
                vec3 purpleColor = vec3(1.0, 0.0, 1.0);
                vec3 greenColor = vec3(1.0, 1.0, 1.0);
                vec3 uvColor = vec3(vUv,1.0);
                float color = step(0.9,sin(cnoise(vUv * 10.0)*20.0))  ;

                vec3 mixColor =  mix(greenColor,uvColor,color);
                // gl_FragColor =vec4(mixColor,1.0);
                gl_FragColor =vec4(mixColor,1.0);
            `);
            setFrag(meshs[52], '', ``, "gl_FragColor =vec4(color,color,color,1.0);")




        }

        function addCNoise(mesh) {
            setFrag(mesh, '', `
            //	Classic Perlin 2D Noise 
            //	by Stefan Gustavson
            //
            vec4 permute(vec4 x)
            {
                return mod(((x*34.0)+1.0)*x, 289.0);
            }

            vec2 fade(vec2 t)
            {
                return t*t*t*(t*(t*6.0-15.0)+10.0);
            }

            float cnoise(vec2 P)
            {
                vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);
                vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);
                Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation
                vec4 ix = Pi.xzxz;
                vec4 iy = Pi.yyww;
                vec4 fx = Pf.xzxz;
                vec4 fy = Pf.yyww;
                vec4 i = permute(permute(ix) + iy);
                vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024...
                vec4 gy = abs(gx) - 0.5;
                vec4 tx = floor(gx + 0.5);
                gx = gx - tx;
                vec2 g00 = vec2(gx.x,gy.x);
                vec2 g10 = vec2(gx.y,gy.y);
                vec2 g01 = vec2(gx.z,gy.z);
                vec2 g11 = vec2(gx.w,gy.w);
                vec4 norm = 1.79284291400159 - 0.85373472095314 * vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11));
                g00 *= norm.x;
                g01 *= norm.y;
                g10 *= norm.z;
                g11 *= norm.w;
                float n00 = dot(g00, vec2(fx.x, fy.x));
                float n10 = dot(g10, vec2(fx.y, fy.y));
                float n01 = dot(g01, vec2(fx.z, fy.z));
                float n11 = dot(g11, vec2(fx.w, fy.w));
                vec2 fade_xy = fade(Pf.xy);
                vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);
                float n_xy = mix(n_x.x, n_x.y, fade_xy.y);
                return 2.3 * n_xy;
            }
                // fragmentFn;
            `, '// fragmentFn;');
        }
        function addNoise(mesh) {
            setFrag(mesh, '', `
                // 随机函数
                float random (vec2 st) {
                    return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
                }
                // 噪声函数
                float noise (in vec2 _st) {
                    vec2 i = floor(_st);
                    vec2 f = fract(_st);

                    // Four corners in 2D of a tile
                    float a = random(i);
                    float b = random(i + vec2(1.0, 0.0));
                    float c = random(i + vec2(0.0, 1.0));
                    float d = random(i + vec2(1.0, 1.0));

                    vec2 u = f * f * (3.0 - 2.0 * f);

                    return mix(a, b, u.x) +
                            (c - a)* u.y * (1.0 - u.x) +
                            (d - b) * u.x * u.y;
                }
                // fragmentFn;
            `, '// fragmentFn;');
        }



        function rotateLD() {
            meshs[42].material.uniforms.uTime = { value: 0 }
            // 添加旋转函数
            setFrag(meshs[42], '', `
            // 旋转函数
            vec2 rotate(vec2 uv, float rotation, vec2 mid)
            {
                return vec2(
                cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
                cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
                );
            }
            // fragmentFn;
            `, '// fragmentFn;');
            // 添加uTime
            setFrag(meshs[42], '', `
            uniform float uTime;
            `, '// fragmentFn;')
            setFrag(meshs[42], '通过时间实现动态选择', `
                // vec2 rotateUv = rotate(vUv,3.14*0.25,vec2(0.5));
                vec2 rotateUv = rotate(vUv,-uTime*5.0,vec2(0.5));
                float alpha =  1.0 - step(0.5,distance(vUv,vec2(0.5)));
                float angle = atan(rotateUv.x-0.5,rotateUv.y-0.5);
                float color = (angle+3.14)/6.28;
                gl_FragColor =vec4(color,color,color,alpha);
            `);
            setFrag(meshs[42], '', ``, "gl_FragColor =vec4(color,color,color,1.0);")

            gsap.to(meshs[42].material.uniforms.uTime, {
                value: 6.28,
                duration: 5,
                repeat: -1,
                onUpdate: () => {

                },
            });
        }

        function ripple1() {
            addCNoise(meshs[50]);
            meshs[50].material.uniforms.uTime = { value: 0 }
            setFrag(meshs[50], '', ` uniform float uTime; `, '// fragmentFn;')
            setFrag(meshs[50], '波纹效果', `
                float color = sin(cnoise(vUv * 5.0)*5.0+uTime);
            `);
            gsap.to(meshs[50].material.uniforms.uTime, {
                value: 6.28,
                duration: 10,
                repeat: -1,
                onUpdate: () => { },
            });

        }
        function ripple() {
            addCNoise(meshs[47]);
            meshs[47].material.uniforms.uTime = { value: 0 }
            meshs[47].material.uniforms.uScale = { value: 0 }
            setFrag(meshs[47], '', ` uniform float uTime;uniform float uScale; `, '// fragmentFn;')
            setFrag(meshs[47], '通过时间设置波形', `
                float color = step(uScale,cnoise(vUv * 10.0+uTime)) ;
            `);
            gsap.to(meshs[47].material.uniforms.uTime, {
                value: 6.28,
                duration: 10,
                repeat: -1,
                onUpdate: () => { },
            });
            gsap.to(meshs[47].material.uniforms.uScale, {
                value: 0.5,
                duration: 10,
                repeat: -1,
                onUpdate: () => { },
            });
        }


        function rotateDarts() {
            meshs[31].material.uniforms.uTime = { value: 0 }
            // 添加旋转函数
            setFrag(meshs[31], '', `
            // 旋转函数
            vec2 rotate(vec2 uv, float rotation, vec2 mid)
            {
                return vec2(
                cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
                cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
                );
            }
            // fragmentFn;
            `, '// fragmentFn;');
            // 添加uTime
            setFrag(meshs[31], '', `
            uniform float uTime;
            `, '// fragmentFn;')
            // 替换color
            setFrag(meshs[31], '旋转uv', `
                vec2 rotateUv = rotate(vUv,-uTime*5.0,vec2(0.5));
                float  color = 0.5 / distance(vec2(rotateUv.x,(rotateUv.y-0.5)*5.0+0.5),vec2(0.5,0.5)) - 1.0;
                color += 0.5 / distance(vec2(rotateUv.y,(rotateUv.x-0.5)*5.0+0.5),vec2(0.5,0.5)) - 1.0;
            `)
            // 替换color
            setFrag(meshs[31], '', `gl_FragColor =vec4(color,color,color,color);`, "gl_FragColor =vec4(color,color,color,1.0);")
            gsap.to(meshs[31].material.uniforms.uTime, {
                value: 6.28,
                duration: 5,
                repeat: -1,
                onUpdate: () => {

                },
            });
        }

        function setFrag(mesh, title, str, materialStr = 'float color = 1.0;') {

            mesh.material.fragmentShader = mesh.material.fragmentShader.replace(
                `${materialStr}`,
                [`//${title}`, str].join("\n")

            )

        }



        /*
        点击复制代码
        */
        const raycaster = new THREE.Raycaster();
        const pointer = new THREE.Vector2();

        window.addEventListener("click", (event) => {
            event.stopPropagation()
            pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
            pointer.y = - (event.clientY / window.innerHeight) * 2 + 1;

            raycaster.setFromCamera(pointer, camera);
            const intersects = raycaster.intersectObjects(meshs);

            if (intersects.length) {
                const textfrag = intersects[0].object.material.fragmentShader;
                const textvert = intersects[0].object.material.vertexShader;
                const text = `vertexShader:"${textvert}",` + ' ' + `fragmentShader:"${textfrag}"`

                if (!textfrag || !textvert || text.indexOf('main()') == -1) {
                    addTast('代码复制失败,请刷新后重新尝试!')
                    return;
                }

                const copyEl = document.getElementById("copy");
                copyEl.setAttribute("data-clipboard-text", text);
                copyEl.click();
            }
        });

        var clipboard = new ClipboardJS('#copy');
        var txtel = document.createElement('div');
        clipboard.on('success', function (e) {

            addTast('代码复制成功!<br/>'); // + e.text
            e.clearSelection();
        });

        function addTast(text) {
            txtel.setAttribute("class", 'toast');
            txtel.innerHTML = text;
            document.body.appendChild(txtel);
            if (txtel) {
                setTimeout(() => {
                    document.body.removeChild(txtel)
                }, 3000)
            }

        }





    </script>

</body>

</html>